import kyo.*;

public class FiveChess {
    int w, h;
    private char board[][] = null;
    private int r = 0, c = 0;
    private char turn;

    public FiveChess() {
        this(31, 15);
    }

    public FiveChess(int w, int h) {
        this.w = w;
        this.h = h;
        board = new char[h][w];
        init();
        Kyo.init();
        Vt.cmd(VtCmd.CLEAR).gotoxy(r + 1, c + 1);
        show();
    }

    public FiveChess init() {
        c = w / 2;
        r = h / 2;
        boardInit();
        turn = '#';
        Vt.gotoxy(r + 1, c + 1);
        return this;
    }

    public FiveChess boardInit() {
        for (int i = 0; i < h; ++i) {
            for (int j = 0; j < w; ++j) {
                board[i][j] = '+';
            }
        }
        return this;
    }

    public FiveChess show() {
        Vt.cmd(VtCmd.SAVE).cmd(VtCmd.HIDE).gotoxy(1, 1);
        for (int i = 0; i < h; ++i) {
            for (int j = 0; j < w; ++j) {
                System.out.printf("%c", board[i][j]);
            }
            System.out.println();
        }
        Vt.cmd(VtCmd.SHOW).cmd(VtCmd.LOAD);
        return this;
    }

    private boolean _checkWin(int x, int y) {
        int k, ch = '0', count = 0;

        int i = r - 4 * x;
        int j = c - 4 * y;

        for (k = 0; k < 9; ++k, i += 1 * x, j += 1 * y) {
            if (i < 0 || j < 0 || i > h - 1 || j > w - 1) {
                continue;
            }

            if (ch == board[i][j]) {
                count++;
            } else {
                count = 1;
                ch = board[i][j];
            }

            if (count == 5)
                return true;
        }

        return false;
    }

    public int checkWin() {
        char ch;
        int i, j, count = 0;

        if (_checkWin(1, 0)
                || _checkWin(0, 1)
                || _checkWin(1, 1)
                || _checkWin(1, -1))
            return 3;

/* {
 *         // 横向判断
 *         for (i = c - 4, ch = '0'; i <= c + 4; ++i) {
 *             if (i < 0 || i > w - 1) {
 *                 continue;
 *             }
 * 
 *             if (ch == board[r][i]) {
 *                 count++;
 *             } else {
 *                 count = 1;
 *                 ch = board[r][i];
 *             }
 * 
 *             if (count == 5)
 *                 return 3;
 *         }
 * 
 *         // 竖向判断
 *         for (i = r - 4, ch = '0'; i <= r + 4; ++i) {
 *             if (i < 0 || i > h - 1) {
 *                 continue;
 *             }
 * 
 *             if (ch == board[i][c]) {
 *                 count++;
 *             } else {
 *                 count = 1;
 *                 ch = board[i][c];
 *             }
 * 
 *             if (count == 5)
 *                 return 3;
 *         }
 * 
 *         // 正斜判断
 *         for (i = r - 4, j = c - 4, ch = '0'; i <= r + 4; ++i, ++j) {
 *             if (i < 0 || j < 0 || i > h - 1 || j > w - 1) {
 *                 continue;
 *             }
 * 
 *             if (ch == board[i][j]) {
 *                 count++;
 *             } else {
 *                 count = 1;
 *                 ch = board[i][j];
 *             }
 * 
 *             if (count == 5)
 *                 return 3;
 *         }
 * 
 *         // 反斜判断
 *         for (i = r - 4, j = c + 4, ch = '0'; i <= r + 4; ++i, --j) {
 *             if (i < 0 || j < 0 || i > h - 1 || j > w - 1) {
 *                 continue;
 *             }
 * 
 *             if (ch == board[i][j]) {
 *                 count++;
 *             } else {
 *                 count = 1;
 *                 ch = board[i][j];
 *             }
 * 
 *             if (count == 5)
 *                 return 3;
 *         }
 *  }
 */

        for (i = 0; i < h; ++i) {
            for (j = 0; j < w; ++j) {
                if (board[i][j] == '+')
                    return 2;
            }
        }

        return 4;
    }

    public int pressChess() {
        if (board[r][c] != '+') {
            return 1;
        }

        board[r][c] = turn;
        turn = (turn == '#') ? '@' : '#';

        return checkWin();
    }

    public boolean chessHandle() {
        switch (pressChess()) {
            case 1: //下子失败
                break;
            case 2: //下子成功
                show();
                break;
            case 3: //输赢
                show();
                Vt.gotoxy(h + 1, 1);
                if (turn == '#') {
                    System.out.printf("白方羸!\n");
                } else {
                    System.out.printf("黑方羸!\n");
                }
                init();
                show();
                break;
            case 4: //和棋
                show();
                Vt.gotoxy(h + 1, 1);
                System.out.printf("和棋!\n");
                init();
                show();
                break;
        }

        return false;
    }

    public boolean keyHandle(int key) {
        switch (key) {
            case 27:
                return true;
            case 'w':
                if (r > 0) {
                    Vt.move(VtDirect.UP, 1);
                    r--;
                }
                break;
            case 's':
                if (r < h - 1) {
                    Vt.move(VtDirect.DOWN, 1);
                    r++;
                }
                break;
            case 'a':
                if (c > 0) {
                    Vt.move(VtDirect.LEFT, 1);
                    c--;
                }
                break;
            case 'd':
                if (c < w - 1) {
                    Vt.move(VtDirect.RIGHT, 1);
                    c++;
                }
                break;
            case 32:
                return chessHandle();
        }

        return false;
    }

    public FiveChess run() {
        while (!keyHandle(Kyo.key()))
            ;
        Kyo.exit();
        Vt.gotoxy(h + 2, 1);
        return this;
    }
}
